//
//  BattleScene.swift
//  aircraftBattle1
//
//  Created by 许洋 on 2024/5/16.
//

import SpriteKit
import GameplayKit
import CoreMotion
import AVFoundation

struct  CrashCategory {
    static let BulletBlue:UInt32 = 0x1 << 2
    static let Enemy     :UInt32 = 0x1 << 3
    static let SpaceShip :UInt32 = 0x1 << 4
    static let Emitt     :UInt32 = 0x1 << 5
    static let None      :UInt32 = 0
}

class BattleScene: BaseScene,SKPhysicsContactDelegate {

    private var aircraftNode:SKSpriteNode!  // 玩家 宇宙飞船
    private var cSNode:SKLabelNode! // 当前分数节点
    private var cScore:Int = 0
//    private var hScorenNode:SKLabelNode!    // 最高分数
    private var controlNode:SKSpriteNode!  // 控制按钮

    private var hScore:Int = 0
    private var avPlayer:AVAudioPlayer!
    private var begianLoc:CGPoint!
    private var timer:Timer!  // timer
    private var gameState:NSInteger!  // gameState 1 game starting 2 pause 3 over
//    private var enemys:Array!  // gameState 1 game starting 2 pause 3 over

    var lastUpdateTimeInterval:TimeInterval = 0
    var deltaTime:TimeInterval = 0
    private var selectIndex:Int = 0
    private var airTypes:Array<String> = []
    private var mapTypes:Array<String> = []
    private var mapSelectIndex:Int = 0
    private var zidanImgName:String = ""

    override func didMove(to view: SKView) {
        
        physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
        physicsWorld.contactDelegate = self
//        enemys = Array()
        airTypes = ["air_y","air_b","air_g"]
        mapTypes = ["battle_bg_1","battle_bg_2","battle_bg_3"]

        gameState = 1
        cSNode = childNode(withName: "currentScore") as? SKLabelNode
//        hScorenNode    = childNode(withName: "highScore") as? SKLabelNode
        controlNode = childNode(withName: "controlNode") as? SKSpriteNode
        controlNode.texture = SKTexture(imageNamed: "zanting")

        let y = self.size.height/2.7
        cSNode.position = CGPoint(x: 0, y: y)
        controlNode.position = CGPoint(x: (self.view?.bounds.size.width)! , y: y+30)

        if !UserDefaults.standard.bool(forKey: "HIGHSCORE") {
            UserDefaults.standard.set(0, forKey: "CURRENTSCORE")
            UserDefaults.standard.set(0, forKey: "HIGHSCORE")
        }
        UserDefaults.standard.set(0, forKey: "CURRENTSCORE")
        hScore = UserDefaults.standard.integer(forKey: "HIGHSCORE")


//        hScorenNode.text = "HIGH:\(hScore)"
        
        // 背景音乐
        let path = Bundle.main.path(forResource: "background", ofType: "mp3")
        let pathUrl = URL(fileURLWithPath: path!)
        
        do {
            try avPlayer = AVAudioPlayer(contentsOf: pathUrl)
        }catch {
            return
        }
        
        avPlayer.play()
        avPlayer.volume = 0.2
        selectIndex =  UserDefaults.standard.integer(forKey: "AIRTYPE")
        mapSelectIndex =  UserDefaults.standard.integer(forKey: "MAPTYPE")
        switch selectIndex{
        case 0:
            zidanImgName = "Bullet_Y"
        case 1:
            zidanImgName = "Bullet_B"
        case 2:
            zidanImgName = "Bullet_G"
        default:
            zidanImgName = "Bullet_Y"

        }
        let texture = SKTexture(imageNamed: airTypes[selectIndex])
//        aircraftNode.size = CGSize(width: texture.size().width*3, height: texture.size().height*3)
        aircraftNode = childNode(withName: "SpaceShip") as! SKSpriteNode?
        aircraftNode.texture = texture
        aircraftNode.physicsBody = SKPhysicsBody(texture: texture, size: aircraftNode.size)
        // aircraftNode.physicsBody = SKPhysicsBody(circleOfRadius: self.aircraftNode.size.width / 2)
        aircraftNode.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "air_y"), size: SKTexture(imageNamed: "air_y").size())
        aircraftNode.physicsBody?.affectedByGravity = false
        aircraftNode.physicsBody?.isDynamic = true
        aircraftNode.physicsBody?.categoryBitMask    = CrashCategory.SpaceShip
        aircraftNode.physicsBody?.contactTestBitMask = CrashCategory.Enemy
        aircraftNode.physicsBody?.collisionBitMask   = CrashCategory.None
        let aircraftNodey = -(self.size.height/2 - aircraftNode.size.height*2)
        aircraftNode.position = CGPoint(x: 0, y: aircraftNodey)


        enumerateChildNodes(withName: "bgNode") { (node, _) in
            guard let sprite = node as? SKSpriteNode else {
                return
            }
            sprite.texture = SKTexture(imageNamed: self.mapTypes[self.mapSelectIndex])
            sprite.size = self.size
        }


        timer = Timer.scheduledTimer(timeInterval: TimeInterval(0.5), target: self, selector: #selector(BattleScene.timerAction), userInfo: nil, repeats: true)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.location(in: self)
            
            let nodeX = self.aircraftNode.position.x;
            let nodey = self.aircraftNode.position.y;
            let x = location.x - self.begianLoc.x;
            self.aircraftNode.position = CGPoint(x: nodeX+x, y: nodey);
            self.begianLoc = location;
        }

    }
    func  updateBackground(deltaTime:TimeInterval){
        enumerateChildNodes(withName: "bgNode") { (node, _) in
            guard let sprite = node as? SKSpriteNode else {
                return
            }
            sprite.position.y -= CGFloat(deltaTime * 300)
            if sprite.position.y < -self.frame.size.height {
              sprite.position.y += 2 * self.frame.size.height
            }
        }
        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {
            return
        }
        let location = touch.location(in: self) // touchLocation
        self.begianLoc = location;
        let touchLocation = touch.location(in: self)
        if  controlNode.contains(touchLocation) {
            if gameState == 1{
                gameState = 2
                timer.fireDate = Date.distantFuture
                controlNode.texture = SKTexture(imageNamed: "jixu")
                enumerateChildNodes(withName: "Enemy") { (node, _) in
                    guard let sprite = node as? SKSpriteNode else {
                        return
                    }
                    sprite.removeAllActions()
                }
                enumerateChildNodes(withName: "BulletNode") { (node, _) in
                    guard let sprite = node as? SKSpriteNode else {
                        return
                    }
                    sprite.removeAllActions()
                }


            }else if gameState == 2{
                gameState = 1
                controlNode.texture = SKTexture(imageNamed: "zanting")
                timer?.fireDate = Date.init(timeIntervalSinceNow: 0)
                enumerateChildNodes(withName: "Enemy") { (node, _) in
                    guard let sprite = node as? SKSpriteNode else {
                        return
                    }
                    let duration = CGFloat.random(min: CGFloat(1.0), max: CGFloat(3.8))
                    let actionDown = SKAction.move(to: CGPoint(x: sprite.position.x, y: -self.frame.size.height), duration: TimeInterval(duration))
                    sprite.run(SKAction.sequence([actionDown,
                                                 SKAction.run({
                        sprite.removeFromParent()
                                                 })]))
                }
                enumerateChildNodes(withName: "BulletNode") { (node, _) in
                    guard let sprite = node as? SKSpriteNode else {
                        return
                    }
                    let moveTo = CGPoint(x:sprite.position.x, y: self.aircraftNode.position.y + self.frame.size.height)

                    sprite.run(SKAction.sequence([
                    SKAction.move(to: moveTo, duration: TimeInterval(2)),
                    SKAction.run({
                        sprite.removeAllChildren() // 移除 emitterNode
                        sprite.removeFromParent() // 移除 子弹bulltedNode
                        sprite.removeFromParent()  // 移除 trailNode
                    })]))
                }



            }
            
        }
        
    }
    
    // MARK: - 生成并发射子弹;
    func generatingBulletAndFire(x:CGFloat){
        let bulletNode = SKSpriteNode(imageNamed: zidanImgName)
        bulletNode.name = "BulletNode";
        bulletNode.position.x = aircraftNode.position.x
        bulletNode.position.y = aircraftNode.position.y + aircraftNode.size.height / 2
        bulletNode.zPosition = 1
        let w = SKTexture(imageNamed: zidanImgName).size().width * 3
        let h = SKTexture(imageNamed: zidanImgName).size().height * 3
        bulletNode.size = CGSize(width: w, height: h)
        self.addChild(bulletNode)
        bulletNode.physicsBody = SKPhysicsBody(circleOfRadius: bulletNode.size.width / 2)
        bulletNode.physicsBody?.affectedByGravity = false
        bulletNode.physicsBody?.categoryBitMask   =  CrashCategory.BulletBlue
        bulletNode.physicsBody?.contactTestBitMask = CrashCategory.Enemy
        bulletNode.physicsBody?.collisionBitMask = CrashCategory.None
        bulletNode.physicsBody?.usesPreciseCollisionDetection = true
        
        let moveTo = CGPoint(x: aircraftNode.position.x + x, y: aircraftNode.position.y + self.frame.size.height)
        let trailNode = SKNode()
        trailNode.zPosition = 1
        //trailNode.name = "trail"
        addChild(trailNode)
        bulletNode.run(SKAction.sequence([
        SKAction.move(to: moveTo, duration: TimeInterval(2)),
        SKAction.run({
        bulletNode.removeAllChildren() // 移除 emitterNode
        bulletNode.removeFromParent() // 移除 子弹bulltedNode
        trailNode.removeFromParent()  // 移除 trailNode
        })]))
       
        
    }
    // 开火
    @objc func bulletFire() {
        let actionFire = SKAction.playSoundFileNamed("torpedo.mp3", waitForCompletion: false)
        run(actionFire)
//        generatingBulletAndFire(x:-600) // 生成并发射子弹
//        generatingBulletAndFire(x:-400) // 生成并发射子弹
//        generatingBulletAndFire(x:-200) // 生成并发射子弹
        generatingBulletAndFire(x:0) // 生成并发射子弹
//        generatingBulletAndFire(x:200) // 生成并发射子弹
//        generatingBulletAndFire(x:400) // 生成并发射子弹
//        generatingBulletAndFire(x:600) // 生成并发射子弹

    }
    @objc func timerAction(){
        createEnemyAircraft()
        bulletFire()
    }
    @objc func createEnemyAircraft() {
        
        let i = Int(arc4random_uniform(4)) + 1
        
        let imageName = "enemy_\(i)"
        let enemy  = SKSpriteNode(imageNamed: imageName)
        enemy.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        enemy.size = CGSize(width: SKTexture(imageNamed: imageName).size().width * 3, height: SKTexture(imageNamed: imageName).size().height * 3)
        enemy.zPosition   = 1
        enemy.name = "Enemy"
        var xPosition:CGFloat = 0.0
        xPosition = CGFloat.random(min: -self.frame.size.width / 2 + enemy.size.width, max: self.frame.size.width / 2  - enemy.size.width)
        enemy.position = CGPoint(x: xPosition, y: self.frame.size.height / 2  + enemy.size.height * 2)
        self.addChild(enemy)
        enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width / 2)
        enemy.physicsBody?.affectedByGravity = false
        enemy.physicsBody?.categoryBitMask   = CrashCategory.Enemy
        enemy.physicsBody?.contactTestBitMask = CrashCategory.BulletBlue | CrashCategory.SpaceShip
        enemy.physicsBody?.collisionBitMask   = CrashCategory.None
        
        let duration = CGFloat.random(min: CGFloat(1.0), max: CGFloat(3.8))
        let actionDown = SKAction.move(to: CGPoint(x: xPosition, y: -self.frame.size.height), duration: TimeInterval(duration))
        enemy.run(SKAction.sequence([actionDown,
                                     SKAction.run({
            enemy.removeFromParent()
                                     })]))
        
    }
    
 
    func bulletsHitTheAircraft(nodeA:SKSpriteNode,nodeB:SKSpriteNode){
        let explosion = SKEmitterNode(fileNamed: "AircraftExplode1")!
        
        explosion.particleTexture = nodeB.texture
        explosion.position = nodeB.position
        self.addChild(explosion)
        
        explosion.run(SKAction.sequence([
            SKAction.wait(forDuration: 0.3),
            SKAction.run {
                explosion.removeFromParent()
            }]))
        let actionColision = SKAction.playSoundFileNamed("explosion.mp3", waitForCompletion: false)
        run(actionColision)
        
        cScore += 1
        cSNode.text = "SCORE:\(cScore)"
        UserDefaults.standard.set(cScore, forKey: "CURRENTSCORE")
        
        if cScore > hScore {
            hScore = cScore
            UserDefaults.standard.set(cScore, forKey: "HIGHSCORE")
            GameCenterManager.shared.reportScore(score: cScore)
        }
        if nodeA.physicsBody?.categoryBitMask == CrashCategory.BulletBlue {
            nodeA.removeAllChildren() // 移除所有子效果 emitter
            nodeA.isHidden = true     // 子弹隐藏
            nodeA.physicsBody?.categoryBitMask = 0 // 设置子弹不会再发生碰撞
            nodeB.removeFromParent()  // 移除外星人
        }else if nodeB.physicsBody?.categoryBitMask == CrashCategory.BulletBlue {
            nodeA.removeFromParent()  // 移除外星人
            nodeB.removeAllChildren()
            nodeB.isHidden =  true
            nodeB.physicsBody?.categoryBitMask = 0
        }
    }
    
    func enemyAircraftHiTheAircraft(nodeA:SKSpriteNode,nodeB:SKSpriteNode){
        if (nodeA.physicsBody?.categoryBitMask == CrashCategory.Enemy  || nodeB.physicsBody?.categoryBitMask == CrashCategory.Enemy) && (nodeA.physicsBody?.categoryBitMask == CrashCategory.SpaceShip || nodeB.physicsBody?.categoryBitMask == CrashCategory.SpaceShip) {
            let explosion = SKEmitterNode(fileNamed: "AircraftExplode")!
            explosion.position = nodeA.position
            self.addChild(explosion)
            nodeA.removeFromParent()
            nodeB.removeFromParent()
            let loseMusicAction = SKAction.playSoundFileNamed("", waitForCompletion: false)
            self.run(SKAction.sequence([
                loseMusicAction,
                SKAction.wait(forDuration: TimeInterval(0.7)),
                SKAction.run {
                    self.avPlayer.stop()
                    let reveal = SKTransition.doorsOpenHorizontal(withDuration: TimeInterval(0.5))
                    let loseScene = GameOverScene(fileNamed: "GameOverScene")
                    loseScene?.size = self.size
                    loseScene?.viewController = self.viewController
                    loseScene?.scaleMode = .aspectFill
                    self.view?.presentScene(loseScene!, transition: reveal)
                }]))
        }
        
    }
    
    func didBegin(_ contact: SKPhysicsContact) {
        
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
        switch contactMask {
            case CrashCategory.Enemy | CrashCategory.BulletBlue:
            bulletsHitTheAircraft(nodeA: contact.bodyA.node as! SKSpriteNode,nodeB: contact.bodyB.node as! SKSpriteNode)
                break
            case CrashCategory.Enemy | CrashCategory.SpaceShip:
            enemyAircraftHiTheAircraft(nodeA: contact.bodyA.node as! SKSpriteNode, nodeB: contact.bodyB.node as! SKSpriteNode)
                break
            default:
                break
        }
    }
    override func update(_ currentTime: TimeInterval) {
        if gameState == 2{
            return
        }
        updateBackground(deltaTime: 0.016)
    }
    
}
